package com.hsurosy.hsuchain.nft.gateway.auth;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.hsurosy.hsuchain.nft.api.user.constant.UserPermission;
import com.hsurosy.hsuchain.nft.api.user.constant.UserRole;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Sa-Token全局配置类
 *
 * @Author Hsu琛君珩
 * @Date 2024-10-06 16:45
 * @Description
 * @Version: v1.0.0
 */
@Configuration
@Slf4j
public class SaTokenConfigure {

    /**
     * 配置Sa-Token的Reactor过滤器
     *
     * @return 配置好的SaReactorFilter
     */
    @Bean
    public SaReactorFilter getSaReactorFilter() {
        return new SaReactorFilter()
                // 拦截地址，拦截所有请求
                .addInclude("/**")
                // 开放地址，不拦截/favicon.ico
                .addExclude("/favicon.ico")
                // 鉴权方法，每次访问时会执行以下鉴权逻辑
                .setAuth(obj -> {
                    // 登录校验，拦截所有路由，除去开放的/auth/login、/collection/collectionList等接口
                    SaRouter.match("/**").notMatch("/auth/**", "/collection/collectionList", "/collection/collectionInfo", "/wxPay/**").check(r -> StpUtil.checkLogin());

                    // 权限认证，不同模块校验不同的角色和权限
                    SaRouter.match("/admin/**", r -> StpUtil.checkRole(UserRole.ADMIN.name()));
                    SaRouter.match("/trade/**", r -> StpUtil.checkPermission(UserPermission.AUTH.name()));

                    // 检查用户权限
                    SaRouter.match("/user/**", r -> StpUtil.checkPermissionOr(UserPermission.BASIC.name(), UserPermission.FROZEN.name()));
                    SaRouter.match("/order/**", r -> StpUtil.checkPermissionOr(UserPermission.BASIC.name(), UserPermission.FROZEN.name()));
                })
                // 异常处理，处理鉴权过程中抛出的异常
                .setError(this::getSaResult);
    }

    /**
     * 处理Sa-Token的异常，返回自定义的错误信息
     *
     * @param throwable 捕获到的异常
     * @return 统一格式的SaResult错误响应
     */
    private SaResult getSaResult(Throwable throwable) {
        switch (throwable) {
            case NotLoginException notLoginException:
                // 未登录异常处理
                log.error("请先登录");
                return SaResult.error("请先登录");
            case NotRoleException notRoleException:
                // 角色不匹配异常处理
                if (UserRole.ADMIN.name().equals(notRoleException.getRole())) {
                    log.error("请勿越权使用！");
                    return SaResult.error("请勿越权使用！");
                }
                log.error("您无权限进行此操作！");
                return SaResult.error("您无权限进行此操作！");
            case NotPermissionException notPermissionException:
                // 权限不足异常处理
                if (UserPermission.AUTH.name().equals(notPermissionException.getPermission())) {
                    log.error("请先完成实名认证！");
                    return SaResult.error("请先完成实名认证！");
                }
                log.error("您无权限进行此操作！");
                return SaResult.error("您无权限进行此操作！");
            default:
                // 其他异常处理
                return SaResult.error(throwable.getMessage());
        }
    }
}
